package com.zg.message.channel;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zg.common.core.dao.message.entity.MsgInfo;
import com.zg.message.channel.support.SysEncryptionUtil;
import com.zg.message.config.JmSmsConfig;
import com.zg.message.config.MhSmsConfig;
import com.zg.message.service.MsgInfoService;
import com.zg.message.sys.SendStateEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>Description: </p>
 *
 * @author zhanfeng.liang
 * @since 2025/7/9 14:31
 */

@Service
@Slf4j
public class SmsChannel implements IChannel {

    @Autowired
    private MsgInfoService msgInfoService;

    @Autowired
    private JmSmsConfig jmSmsConfig;

    @Autowired
    private MhSmsConfig mhSmsConfig;

    private  static  String charSet = "UTF-8";

    @Override
    public boolean send(MsgInfo msgInfo) {
        String state = SendStateEnum.SUCCESS.getValue();
        try {
            log.info("send sms");
//            List<String> list = Lists.newArrayList();
//            list.add(msgInfo.getReceiverAdd());
//            sendJmMessage(msgInfo.getContent(), list);
            sendMhMessage(msgInfo);
            return true;
        } catch (Exception e) {
            log.error(jmSmsConfig.getUserName());
            log.error("发送短信异常：{}", e.getMessage());
            state = SendStateEnum.FAIL.getValue();
            return false;
        } finally {
            msgInfo.setSendTime(new Date());
            msgInfo.setSendState(state);
            msgInfoService.edit(msgInfo);
        }
    }

    public  boolean sendJmMessage(String sendStr, List<String> list) {
        try {
            String timestemp = getTimestemp();// 时间戳

            String userName = jmSmsConfig.getUserName();
            String password = jmSmsConfig.getPassword();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < list.size(); i++) {
                stringBuilder.append(list.get(i));
                stringBuilder.append(",");
            }
            String mobiles = stringBuilder.substring(0, stringBuilder.length() - 1);
            int priority = jmSmsConfig.getPriority();
            String packID = jmSmsConfig.getPackID();
            String packsID = jmSmsConfig.getPacksID();
            String expandNumber = jmSmsConfig.getExpandNumber();


            String Key = getKey(userName, password, timestemp);// 加密
            // 短信唯一标识 长整型数字。短信ID，用来匹配状态报告（必须数字类型）
            long smsid = System.currentTimeMillis();

            String _StringBuffer = "UserName=" + userName + "&" +
                    "Key=" + Key + "&" +
                    "Timestemp=" + timestemp + "&" +
                    "Content=" + URLEncoder.encode(sendStr, "utf-8") + "&" +
                    "CharSet=utf-8&" +
                    "Mobiles=" + mobiles + "&" +
                    "Priority=" + priority + "&" +
                    "PackID=" + packID + "&" +
                    "PacksID=" + packsID + "&" +
                    "ExpandNumber=" + expandNumber + "&" +
                    "SMSID=" + smsid;

            Hashtable _Header = new Hashtable();
            _Header.put("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
            log.info("发送短信:{}", _StringBuffer);
            // post请求
            InputStream _InputStream = SendMessage(_StringBuffer.getBytes(charSet), _Header, jmSmsConfig.getServer());
            //response：0成功，其它失败
            String response = GetResponseString(_InputStream, charSet);
            log.info("短信返回:{}", response);
            return true;
        } catch (Exception e) {
            log.error("发送短信异常：{}", e.getMessage());
            return false;
        }
    }
    public static InputStream SendMessage(byte[] Content, Hashtable _Header, String serverAddress) {
        return SendMessage(Content, _Header, serverAddress, null, 0, null, null);
    }

    public static InputStream SendMessage(byte[] Content, Hashtable _Header, String serverAddress, String proxyHost, int proxyPort, String userName, String password) {
        InputStream _InputStream = null;

        try {
            if (serverAddress == null)
                return null;

            HttpPost _HttpPost = new HttpPost(serverAddress);
            if (_Header != null) {
                Enumeration _List = _Header.keys();
                String keyString = "";
                try {
                    while (_List.hasMoreElements()) {
                        keyString = _List.nextElement().toString();
                        _HttpPost.addHeader(keyString, _Header.get(keyString).toString());
                    }
                } catch (NoSuchElementException e) {
                    e.printStackTrace();
                }
            }
            _HttpPost.addHeader("Connection", "Keep-Alive");
            _HttpPost.setEntity(new ByteArrayEntity(Content));
            HttpClient _HttpClient = new DefaultHttpClient();
            HttpResponse _HttpResponse = _HttpClient.execute(_HttpPost);

            if (_Header != null) {
                _Header.put("ResponseContentLength", String.valueOf(_HttpResponse.getEntity().getContentLength()));
                Header[] _RespHeader = _HttpResponse.getAllHeaders();
                if (_RespHeader != null && _RespHeader.length > 0) {
                    for (Header header : _RespHeader) {
                        _Header.put(header.getName(), header.getValue());
                    }
                }
            }
            _InputStream = _HttpResponse.getEntity().getContent();
        } catch (Exception e) {
            log.error("请求失败，原因：" + e.getMessage() + "请求地址：" + serverAddress);
        }
        return _InputStream;
    }

    /**
     * 解析返回的流
     *
     * @param _InputStream
     * @return
     */
    public static String GetResponseString(InputStream _InputStream, String Charset) {
        String response = "error:";
        try {
            if (_InputStream != null) {
                StringBuffer buffer = new StringBuffer();
                InputStreamReader isr = new InputStreamReader(_InputStream, Charset);
                Reader in = new BufferedReader(isr);
                int ch;
                while ((ch = in.read()) > -1) {
                    buffer.append((char) ch);
                }
                response = buffer.toString();
                buffer = null;
            } else {
                response = response + "timeout";
            }
        } catch (Exception e) {
            log.error("获取响应错误，原因：" + e.getMessage());
            response = response + e.getMessage();
        }
        return response;
    }

    /************
     * 获取时间戳
     *
     * @return
     */
    public static String getTimestemp() {
        return new SimpleDateFormat("MMddHHmmss").format(new Date());
    }

    /************
     * 加密处理
     *
     * @param userName
     * @param password
     * @param timestemp
     * @return
     */
    public static String getKey(String userName, String password, String timestemp) {
        String key = "";
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(userName.getBytes());
            mdTemp.update(password.getBytes());
            mdTemp.update(timestemp.getBytes());
            key = bytesToHexString(mdTemp.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return key;
    }

    /**********
     * 字节数组转16进制字符串
     *
     * @param src
     * @return
     */
    public static String bytesToHexString(byte src[]) {
        String resultString = "";
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0)
            return null;
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 255;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2)
                stringBuilder.append(0);
            stringBuilder.append(hv);
        }

        resultString = stringBuilder.toString();
        stringBuilder = null;
        return resultString;
    }

    public boolean sendMhMessage(MsgInfo msgInfo) throws Exception {
        //原始接口请求入参
        JSONObject requestParams = new JSONObject();
        requestParams.set("mobile", msgInfo.getReceiverAdd());
        requestParams.set("content", msgInfo.getContent());
        //排序后的请求入参
        TreeMap<String, Object> sortMap = SysEncryptionUtil.sortField(requestParams);
        //生成签名
        String sign = SysEncryptionUtil.sign(mhSmsConfig.getCustomerPrivateKey(), mhSmsConfig.getAppId(), JSONUtil.toJsonStr(sortMap));
        //入参中加入签名
        sortMap.put("sign", sign);
        //加密数据
        String cipherText = SysEncryptionUtil.encryptEcb(mhSmsConfig.getSm4Key(), JSONUtil.toJsonStr(sortMap));
        //调用统一接口
        HttpRequest post = HttpUtil.createPost(mhSmsConfig.getServer());
        Map<String, String> headers = new HashMap<>();
        headers.put("appId", mhSmsConfig.getAppId());
        post.addHeaders(headers);
        post.body(cipherText);
        //获取返回结果
        log.debug("=====================================请求数据=====================================");
        log.debug(cipherText);
        cn.hutool.http.HttpResponse response = post.executeAsync();
        String responseStr = response.body();
        log.debug("=====================================响应数据=====================================");
        log.debug(responseStr);
        log.debug("=====================================业务处理=====================================");
        JSONObject resultJson = JSONUtil.parseObj(responseStr);
        String code = resultJson.getStr("code");
        if("000".equals( code)){
            return true;
        }else {
            String message = resultJson.getStr("message");
            throw  new RuntimeException(message);

        }

    }
}
